﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace ERModelData
{
    /// <summary>Реализация маркера</summary>
    public class MarkerTransform
    {
        /// <summary>Объект визуализации</summary>
        private Rectangle visuality;
        /// <summary>Конструктор маркера</summary>
        /// <param name="xCenter">Горизонтальная позиция центра</param>
        /// <param name="yCenter">Вертикальная позияция центра</param>
        public MarkerTransform() { }
        public MarkerTransform(int xCenter, int yCenter)
        {
            Refresh(new Point(xCenter, yCenter));
        }
        /// <summary>Обновление расположение маркера</summary>
        /// <param name="newCenter">новые координаты центра</param>
        public void Refresh(Point newCenter)
        {
            visuality = new Rectangle(
                newCenter.X - Config.cMarkerTransform.size,
                newCenter.Y - Config.cMarkerTransform.size,
                Config.cMarkerTransform.size * 2,
                Config.cMarkerTransform.size * 2
                );
        }
        /// <summary>Отрисовка маркера на указанную поверхность</summary>
        /// <param name="g">Поверхность отрисовки</param>
        public void Draw(Graphics g)
        {
            g.DrawEllipse(Config.cMarkerTransform.pen, visuality);
            g.FillEllipse(Config.cMarkerTransform.brush, visuality);
        }
        /// <summary>Определение попадания точкив маркер</summary>
        /// <param name="position">Позиция точки</param>
        /// <returns>Флаг попадения</returns>
        public bool Contains(Point position)
        {
            return visuality.Contains(position);
        }
    }
    /// <summary>Реализация общего массива маркеров</summary>
    public class MarkersTransform
    {
        /// <summary>Массив маркеров</summary>
        public MarkerTransform[] arrayMarkers;
        /// <summary>Необходимый курсор при наведение на маркер</summary>
        public Cursor cursor;
        /// <summary>Отрисовка всех маркеров в массиве на указанную поверхность</summary>
        /// <param name="g">поверхность для отрисовки</param>
        public void Draw(Graphics g)
        {
            foreach (MarkerTransform i in arrayMarkers) i.Draw(g);
        }
        /// <summary>Обновление позиций маркеров</summary>
        /// <param name="newVisual">Новое положение объекта визуализации</param>
        public void Refresh(Point[] points)
        {
            int c = 0;
            foreach (MarkerTransform i in arrayMarkers) i.Refresh(points[c++]);
        }
    }
    /// <summary>Реализация маркеров трансформации сущности</summary>
    public class MarkersTransformEssence : MarkersTransform
    {
        public new Cursor cursor;
        /// <summary>Разрешенные к перемещению края</summary>
        public struct STip
        {
            /// <summary>Верхняя граница</summary>
            public bool Top;
            /// <summary>Нижняя граница</summary>
            public bool Bottom;
            /// <summary>Левая граница граница</summary>
            public bool Left;
            /// <summary>Правая граница</summary>
            public bool Right;
            /// <summary>Запрет на передвижение всех границ</summary>
            public void Clear()
            {
                Top = Bottom = Left = Right = false;
            }
        }
        /// <summary>Разрешенные к передвижению края в выделенном маркере</summary>
        public STip tip;
        /// <summary>Конструктор Маркера сущности</summary>
        /// <param name="ObjectVisuality">Визуальный объект сущности</param>
        public MarkersTransformEssence(EssenceVisuality ObjectVisuality)
        {
            tip.Clear();
            arrayMarkers = new MarkerTransform[8];
            for (int i = 0; i < 8; i++) arrayMarkers[i] = new MarkerTransform();
            Refresh(GetPoints(ObjectVisuality.essenceObject));
        }
        /// <summary>Проверка попадания в маркер</summary>
        /// <param name="position">Позиция курсора</param>
        /// <returns>Ключ попадения</returns>
        public bool Check(Point position)
        {
            tip.Clear();
            for (int i = 0; i < 8; i++)
                if (arrayMarkers[i].Contains(position))
                {
                    switch (i)
                    {
                        case 0: cursor = Cursors.SizeNWSE; tip.Top = tip.Left = true; break;
                        case 1: cursor = Cursors.SizeNWSE; tip.Bottom = tip.Right = true; break;
                        case 2: cursor = Cursors.SizeNESW; tip.Bottom = tip.Left = true; break;
                        case 3: cursor = Cursors.SizeNESW; tip.Top = tip.Right = true; break;
                        case 4: cursor = Cursors.SizeNS; tip.Top = true; break;
                        case 5: cursor = Cursors.SizeNS; tip.Bottom = true; break;
                        case 6: cursor = Cursors.SizeWE; tip.Left = true; break;
                        case 7: cursor = Cursors.SizeWE; tip.Right = true; break;
                    }
                    return true;
                }
            return false;
        }
        /// <summary>Определяет точки центров маркеров сущности</summary>
        /// <param name="rect">Визуальный объект сущности</param>
        /// <returns>Массив точек центров</returns>
        public Point[] GetPoints(Rectangle rect)
        {
            List<Point> l = new List<Point>();
            l.Add(new Point(rect.Left, rect.Top));
            l.Add(new Point(rect.Right, rect.Bottom));
            l.Add(new Point(rect.Left, rect.Bottom));
            l.Add(new Point(rect.Right, rect.Top));
            l.Add(new Point(rect.Left + rect.Size.Width / 2, rect.Top));
            l.Add(new Point(rect.Left + rect.Size.Width / 2, rect.Bottom));
            l.Add(new Point(rect.Left, rect.Top + rect.Size.Height / 2));
            l.Add(new Point(rect.Right, rect.Top + rect.Size.Height / 2));
            return l.ToArray();
        }
    }
}
